#ifndef UTAUSYNTH_H
#define UTAUSYNTH_H

#include <string.h>
#include <fstream>
#include <iostream>
#include <sstream>

#include <sekai/EventList.h>
#include <sekai/PitchModel.h>
#include <sekai/VoiceSampler.h>
#include <sinsy/sinsy.h>

#if 0
import numpy as np
f0_low_limit = 71.0
fs = 44100
fft_size = int(2 ** np.ceil(np.log2(3 * fs / f0_low_limit + 1)))
#endif

#define IMPULSE_RESPONSE_MAX 2048

class UTAUSynth : /*public sinsy::ISynthOutput,*/ public VoiceSampler {
  int _samplerate = 0;
  std::map<std::string, VoiceDef *> _voicemap;
  std::string _utauPath;
  EventList<PhoEvent> _phoEvents;
  float *_impulseResponse;
  int _mbrPeriod = 0;  // FIXME
  PitchModel *_pitch = nullptr;
  // new synth backend
  std::string _synthext;
  int _fft_size;
  float _frame_period;

  void getImpulseResponse(float currentTime, PhoEvent *event,
                          float *impulseResponse, int *impulseResponseLength,
                          float morph);

 protected:
  virtual void addUnit(const std::string &lyric, int, float *, float *);
  virtual void addPitchPointsForNote(float notepos, float length, float f0);
  virtual void addPitchPointsForRest(float notepos, float length);
  virtual bool addOnePulse();
  virtual float getLengthForUnit(const std::string &fileName);

 public:
  UTAUSynth(std::string utauPath, PitchModel *pitch,
            int buffer_size = IMPULSE_RESPONSE_MAX * 4);
  void load(std::string fileName);
  void synthesize(std::string fileName);
  // void load(VoiceRecord *rec, std::string fileName);
  int samplerate() { return _samplerate; }
  void fix();
  virtual std::string getPhoLine(const std::string &fileName,int index){return "";}
};

#endif
